use super::BitWindow;

#[derive(Debug, PartialEq)]
pub struct Error {
    buffer_pos: BitWindow,
    len: usize,
    capacity: usize,
    text: String,
}

#[derive(Clone, Debug)]
struct EncodeValue {
    buffer: &'static [u8],
    bit_count: u32,
}

#[derive(Clone, Debug)]
struct HuffmanEncoder {
    buffer_pos: BitWindow,
    buffer: Vec<u8>,
}

impl HuffmanEncoder {
    fn new() -> HuffmanEncoder {
        HuffmanEncoder {
            buffer_pos: BitWindow::new(),
            buffer: Vec::new(),
        }
    }

    fn ensure_free_space(&mut self, bit_count: u32) {
        let mut end_range = self.buffer_pos.clone();
        end_range.forwards(bit_count);
        end_range.forwards(0);

        // buffer still has enough space to work on
        if self.buffer.len() > end_range.byte as usize {
            return;
        }

        // optimisation to grow capacity before pushing data
        if self.buffer.capacity() <= end_range.byte as usize {
            self.buffer.reserve(((7 * end_range.byte) / 4) as usize);
        }

        let forward =
            end_range.byte as usize - self.buffer.len() + if end_range.bit > 0 { 1 } else { 0 };
        for _ in 0..forward {
            // push filler value that will ends huffman decoding if not
            // modified
            self.buffer.push(255);
        }
    }

    fn put(&mut self, code: u8) -> Result<(), Error> {
        let encode_value = &HPACK_STRING[code as usize];

        self.ensure_free_space(encode_value.bit_count);

        let mut rest = encode_value.bit_count;
        for i in 0..encode_value.buffer.len() {
            let part = encode_value.buffer[i];

            self.buffer_pos.forwards(if rest < 8 { rest } else { 8 });
            rest -= self.buffer_pos.count;

            write_bits(&mut self.buffer, &self.buffer_pos, part)
        }

        Ok(())
    }

    fn ends(self) -> Result<Vec<u8>, Error> {
        Ok(self.buffer)
    }
}

/// Write bits from `value` to the `out` slice
///
/// Write the least significant `pos.count` bits from `value` to the position specified by
/// `(pos.byte, pos.bit)`. Writes may span multiple bytes. `out` is expected to be long enough
/// to write these bits; this is ensured by `HuffmanEncoder::ensure_free_space()`, which is
/// always called prior to calling this function.
///
/// The bits to be written to are expected to be set to 1 when calling this function. Similarly,
/// this function maintains the invariant that unused bits in the output bytes are set to 1.
fn write_bits(out: &mut [u8], pos: &BitWindow, value: u8) {
    debug_assert!(pos.bit < 8);
    debug_assert!(pos.count <= 8);
    debug_assert!(pos.count > 0);

    if (pos.bit + pos.count) <= 8 {
        // Bits to be written to fit in a single byte
        debug_assert_eq!(out[pos.byte as usize] | PAD_LEFT[pos.bit as usize], 255);
        let pad_left = out[pos.byte as usize] | PAD_RIGHT[(8 - pos.bit) as usize];
        let shifted = value << (8 - pos.bit - pos.count) | PAD_LEFT[pos.bit as usize];
        let pad_right = PAD_RIGHT[(8 - pos.count - pos.bit) as usize];
        out[pos.byte as usize] = (pad_left & shifted) | pad_right;
    } else {
        // Bits to be written to span two bytes
        debug_assert_eq!(out[pos.byte as usize] | PAD_LEFT[pos.bit as usize], 255);
        let split = 8 - pos.bit;
        let pad_left = out[pos.byte as usize] | PAD_RIGHT[split as usize];
        let shifted = (value >> (pos.count - split)) | PAD_LEFT[pos.bit as usize];
        out[pos.byte as usize] = pad_left & shifted;

        let rem = 8 - (pos.count - split);
        out[(pos.byte + 1) as usize] = (value << rem) | PAD_RIGHT[rem as usize];
    }
}

const PAD_RIGHT: [u8; 9] = [0, 1, 3, 7, 15, 31, 63, 127, 255];
const PAD_LEFT: [u8; 9] = [0, 128, 192, 224, 240, 248, 252, 254, 255];

macro_rules! bits_encode {
    [ $( ( $len:expr => [ $( $byte:expr ),* ] ), )* ] => {
        [ $(
            EncodeValue{
                buffer: &[ $( $byte as u8 ),* ],
                bit_count: $len
            } ,
        )* ]
    }
}

const HPACK_STRING: [EncodeValue; 256] = bits_encode![
    ( 13 => [0b1111_1111, 0b0001_1000]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0101_1000]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1110, 0b0000_0010]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1110, 0b0000_0011]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1110, 0b0000_0100]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1110, 0b0000_0101]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1110, 0b0000_0110]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1110, 0b0000_0111]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1110, 0b0000_1000]),
    ( 24 => [0b1111_1111, 0b1111_1111, 0b1110_1010]),
    ( 30 => [0b1111_1111, 0b1111_1111, 0b1111_1111, 0b0011_1100]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1110, 0b0000_1001]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1110, 0b0000_1010]),
    ( 30 => [0b1111_1111, 0b1111_1111, 0b1111_1111, 0b0011_1101]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1110, 0b0000_1011]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1110, 0b0000_1100]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1110, 0b0000_1101]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1110, 0b0000_1110]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1110, 0b0000_1111]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1111, 0b0000_0000]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1111, 0b0000_0001]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1111, 0b0000_0010]),
    ( 30 => [0b1111_1111, 0b1111_1111, 0b1111_1111, 0b0011_1110]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1111, 0b0000_0011]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1111, 0b0000_0100]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1111, 0b0000_0101]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1111, 0b0000_0110]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1111, 0b0000_0111]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1111, 0b0000_1000]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1111, 0b0000_1001]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1111, 0b0000_1010]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1111, 0b0000_1011]),
    (  6 => [0b0001_0100]),
    ( 10 => [0b1111_1110, 0b0000_0000]), // '!'
    ( 10 => [0b1111_1110, 0b0000_0001]), // ';'
    ( 12 => [0b1111_1111, 0b0000_1010]), // '#'
    ( 13 => [0b1111_1111, 0b0001_1001]), // '$'
    (  6 => [0b0001_0101]), // '%'
    (  8 => [0b1111_1000]), // '&'
    ( 11 => [0b1111_1111, 0b0000_0010]), // '''
    ( 10 => [0b1111_1110, 0b0000_0010]), // '('
    ( 10 => [0b1111_1110, 0b0000_0011]), // ')'
    (  8 => [0b1111_1001]), // '*'
    ( 11 => [0b1111_1111, 0b0000_0011]), // '+'
    (  8 => [0b1111_1010]), // ','
    (  6 => [0b0001_0110]), // '-'
    (  6 => [0b0001_0111]), // '.'
    (  6 => [0b0001_1000]), // '/'
    (  5 => [0b0000_0000]), // '0'
    (  5 => [0b0000_0001]), // '1'
    (  5 => [0b0000_0010]), // '2'
    (  6 => [0b0001_1001]), // '3'
    (  6 => [0b0001_1010]), // '4'
    (  6 => [0b0001_1011]), // '5'
    (  6 => [0b0001_1100]), // '6'
    (  6 => [0b0001_1101]), // '7'
    (  6 => [0b0001_1110]), // '8'
    (  6 => [0b0001_1111]), // '9'
    (  7 => [0b0101_1100]), // ':'
    (  8 => [0b1111_1011]),
    ( 15 => [0b1111_1111, 0b0111_1100]), // '<'
    (  6 => [0b0010_0000]), // '='
    ( 12 => [0b1111_1111, 0b0000_1011]), // '>'
    ( 10 => [0b1111_1111, 0b0000_0000]), // '?'
    ( 13 => [0b1111_1111, 0b0001_1010]), // '@'
    (  6 => [0b0010_0001]), // 'A'
    (  7 => [0b0101_1101]), // 'B'
    (  7 => [0b0101_1110]), // 'C'
    (  7 => [0b0101_1111]), // 'D'
    (  7 => [0b0110_0000]), // 'E'
    (  7 => [0b0110_0001]), // 'F'
    (  7 => [0b0110_0010]), // 'G'
    (  7 => [0b0110_0011]), // 'H'
    (  7 => [0b0110_0100]), // 'I'
    (  7 => [0b0110_0101]), // 'J'
    (  7 => [0b0110_0110]), // 'K'
    (  7 => [0b0110_0111]), // 'L'
    (  7 => [0b0110_1000]), // 'M'
    (  7 => [0b0110_1001]), // 'N'
    (  7 => [0b0110_1010]), // 'O'
    (  7 => [0b0110_1011]), // 'P'
    (  7 => [0b0110_1100]), // 'Q'
    (  7 => [0b0110_1101]), // 'R'
    (  7 => [0b0110_1110]), // 'S'
    (  7 => [0b0110_1111]), // 'T'
    (  7 => [0b0111_0000]), // 'U'
    (  7 => [0b0111_0001]), // 'V'
    (  7 => [0b0111_0010]), // 'W'
    (  8 => [0b1111_1100]), // 'X'
    (  7 => [0b0111_0011]), // 'Y'
    (  8 => [0b1111_1101]), // 'Z'
    ( 13 => [0b1111_1111, 0b0001_1011]), // '['
    ( 19 => [0b1111_1111, 0b1111_1110, 0b0000_0000]), // '\'
    ( 13 => [0b1111_1111, 0b0001_1100]), // ']'
    ( 14 => [0b1111_1111, 0b0011_1100]), // '^'
    (  6 => [0b0010_0010]), // '_'
    ( 15 => [0b1111_1111, 0b0111_1101]), // '`'
    (  5 => [0b0000_0011]), // 'a'
    (  6 => [0b0010_0011]), // 'b'
    (  5 => [0b0000_0100]), // 'c'
    (  6 => [0b0010_0100]), // 'd'
    (  5 => [0b0000_0101]), // 'e'
    (  6 => [0b0010_0101]), // 'f'
    (  6 => [0b0010_0110]), // 'g'
    (  6 => [0b0010_0111]), // 'h'
    (  5 => [0b0000_0110]), // 'i'
    (  7 => [0b0111_0100]), // 'j'
    (  7 => [0b0111_0101]), // 'k'
    (  6 => [0b0010_1000]), // 'l'
    (  6 => [0b0010_1001]), // 'm'
    (  6 => [0b0010_1010]), // 'n'
    (  5 => [0b0000_0111]), // 'o'
    (  6 => [0b0010_1011]), // 'p'
    (  7 => [0b0111_0110]), // 'q'
    (  6 => [0b0010_1100]), // 'r'
    (  5 => [0b0000_1000]), // 's'
    (  5 => [0b0000_1001]), // 't'
    (  6 => [0b0010_1101]), // 'u'
    (  7 => [0b0111_0111]), // 'v'
    (  7 => [0b0111_1000]), // 'w'
    (  7 => [0b0111_1001]), // 'x'
    (  7 => [0b0111_1010]), // 'y'
    (  7 => [0b0111_1011]), // 'z'
    ( 15 => [0b1111_1111, 0b0111_1110]), // '{'
    ( 11 => [0b1111_1111, 0b0000_0100]), // '|'
    ( 14 => [0b1111_1111, 0b0011_1101]), // '}'
    ( 13 => [0b1111_1111, 0b0001_1101]), // '~'
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1111, 0b0000_1100]),
    ( 20 => [0b1111_1111, 0b1111_1110, 0b0000_0110]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0001_0010]),
    ( 20 => [0b1111_1111, 0b1111_1110, 0b0000_0111]),
    ( 20 => [0b1111_1111, 0b1111_1110, 0b0000_1000]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0001_0011]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0001_0100]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0001_0101]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0101_1001]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0001_0110]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0101_1010]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0101_1011]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0101_1100]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0101_1101]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0101_1110]),
    ( 24 => [0b1111_1111, 0b1111_1111, 0b1110_1011]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0101_1111]),
    ( 24 => [0b1111_1111, 0b1111_1111, 0b1110_1100]),
    ( 24 => [0b1111_1111, 0b1111_1111, 0b1110_1101]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0001_0111]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0110_0000]),
    ( 24 => [0b1111_1111, 0b1111_1111, 0b1110_1110]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0110_0001]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0110_0010]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0110_0011]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0110_0100]),
    ( 21 => [0b1111_1111, 0b1111_1110, 0b0001_1100]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0001_1000]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0110_0101]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0001_1001]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0110_0110]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0110_0111]),
    ( 24 => [0b1111_1111, 0b1111_1111, 0b1110_1111]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0001_1010]),
    ( 21 => [0b1111_1111, 0b1111_1110, 0b0001_1101]),
    ( 20 => [0b1111_1111, 0b1111_1110, 0b0000_1001]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0001_1011]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0001_1100]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0110_1000]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0110_1001]),
    ( 21 => [0b1111_1111, 0b1111_1110, 0b0001_1110]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0110_1010]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0001_1101]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0001_1110]),
    ( 24 => [0b1111_1111, 0b1111_1111, 0b1111_0000]),
    ( 21 => [0b1111_1111, 0b1111_1110, 0b0001_1111]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0001_1111]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0110_1011]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0110_1100]),
    ( 21 => [0b1111_1111, 0b1111_1111, 0b0000_0000]),
    ( 21 => [0b1111_1111, 0b1111_1111, 0b0000_0001]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0010_0000]),
    ( 21 => [0b1111_1111, 0b1111_1111, 0b0000_0010]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0110_1101]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0010_0001]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0110_1110]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0110_1111]),
    ( 20 => [0b1111_1111, 0b1111_1110, 0b0000_1010]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0010_0010]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0010_0011]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0010_0100]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0111_0000]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0010_0101]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0010_0110]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0111_0001]),
    ( 26 => [0b1111_1111, 0b1111_1111, 0b1111_1000, 0b0000_0000]),
    ( 26 => [0b1111_1111, 0b1111_1111, 0b1111_1000, 0b0000_0001]),
    ( 20 => [0b1111_1111, 0b1111_1110, 0b0000_1011]),
    ( 19 => [0b1111_1111, 0b1111_1110, 0b0000_0001]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0010_0111]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0111_0010]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0010_1000]),
    ( 25 => [0b1111_1111, 0b1111_1111, 0b1111_0110, 0b0000_0000]),
    ( 26 => [0b1111_1111, 0b1111_1111, 0b1111_1000, 0b0000_0010]),
    ( 26 => [0b1111_1111, 0b1111_1111, 0b1111_1000, 0b0000_0011]),
    ( 26 => [0b1111_1111, 0b1111_1111, 0b1111_1001, 0b0000_0000]),
    ( 27 => [0b1111_1111, 0b1111_1111, 0b1111_1011, 0b0000_0110]),
    ( 27 => [0b1111_1111, 0b1111_1111, 0b1111_1011, 0b0000_0111]),
    ( 26 => [0b1111_1111, 0b1111_1111, 0b1111_1001, 0b0000_0001]),
    ( 24 => [0b1111_1111, 0b1111_1111, 0b1111_0001]),
    ( 25 => [0b1111_1111, 0b1111_1111, 0b1111_0110, 0b0000_0001]),
    ( 19 => [0b1111_1111, 0b1111_1110, 0b0000_0010]),
    ( 21 => [0b1111_1111, 0b1111_1111, 0b0000_0011]),
    ( 26 => [0b1111_1111, 0b1111_1111, 0b1111_1001, 0b0000_0010]),
    ( 27 => [0b1111_1111, 0b1111_1111, 0b1111_1100, 0b0000_0000]),
    ( 27 => [0b1111_1111, 0b1111_1111, 0b1111_1100, 0b0000_0001]),
    ( 26 => [0b1111_1111, 0b1111_1111, 0b1111_1001, 0b0000_0011]),
    ( 27 => [0b1111_1111, 0b1111_1111, 0b1111_1100, 0b0000_0010]),
    ( 24 => [0b1111_1111, 0b1111_1111, 0b1111_0010]),
    ( 21 => [0b1111_1111, 0b1111_1111, 0b0000_0100]),
    ( 21 => [0b1111_1111, 0b1111_1111, 0b0000_0101]),
    ( 26 => [0b1111_1111, 0b1111_1111, 0b1111_1010, 0b0000_0000]),
    ( 26 => [0b1111_1111, 0b1111_1111, 0b1111_1010, 0b0000_0001]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1111, 0b0000_1101]),
    ( 27 => [0b1111_1111, 0b1111_1111, 0b1111_1100, 0b0000_0011]),
    ( 27 => [0b1111_1111, 0b1111_1111, 0b1111_1100, 0b0000_0100]),
    ( 27 => [0b1111_1111, 0b1111_1111, 0b1111_1100, 0b0000_0101]),
    ( 20 => [0b1111_1111, 0b1111_1110, 0b0000_1100]),
    ( 24 => [0b1111_1111, 0b1111_1111, 0b1111_0011]),
    ( 20 => [0b1111_1111, 0b1111_1110, 0b0000_1101]),
    ( 21 => [0b1111_1111, 0b1111_1111, 0b0000_0110]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0010_1001]),
    ( 21 => [0b1111_1111, 0b1111_1111, 0b0000_0111]),
    ( 21 => [0b1111_1111, 0b1111_1111, 0b0000_1000]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0111_0011]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0010_1010]),
    ( 22 => [0b1111_1111, 0b1111_1111, 0b0010_1011]),
    ( 25 => [0b1111_1111, 0b1111_1111, 0b1111_0111, 0b0000_0000]),
    ( 25 => [0b1111_1111, 0b1111_1111, 0b1111_0111, 0b0000_0001]),
    ( 24 => [0b1111_1111, 0b1111_1111, 0b1111_0100]),
    ( 24 => [0b1111_1111, 0b1111_1111, 0b1111_0101]),
    ( 26 => [0b1111_1111, 0b1111_1111, 0b1111_1010, 0b0000_0010]),
    ( 23 => [0b1111_1111, 0b1111_1111, 0b0111_0100]),
    ( 26 => [0b1111_1111, 0b1111_1111, 0b1111_1010, 0b0000_0011]),
    ( 27 => [0b1111_1111, 0b1111_1111, 0b1111_1100, 0b0000_0110]),
    ( 26 => [0b1111_1111, 0b1111_1111, 0b1111_1011, 0b0000_0000]),
    ( 26 => [0b1111_1111, 0b1111_1111, 0b1111_1011, 0b0000_0001]),
    ( 27 => [0b1111_1111, 0b1111_1111, 0b1111_1100, 0b0000_0111]),
    ( 27 => [0b1111_1111, 0b1111_1111, 0b1111_1101, 0b0000_0000]),
    ( 27 => [0b1111_1111, 0b1111_1111, 0b1111_1101, 0b0000_0001]),
    ( 27 => [0b1111_1111, 0b1111_1111, 0b1111_1101, 0b0000_0010]),
    ( 27 => [0b1111_1111, 0b1111_1111, 0b1111_1101, 0b0000_0011]),
    ( 28 => [0b1111_1111, 0b1111_1111, 0b1111_1111, 0b0000_1110]),
    ( 27 => [0b1111_1111, 0b1111_1111, 0b1111_1101, 0b0000_0100]),
    ( 27 => [0b1111_1111, 0b1111_1111, 0b1111_1101, 0b0000_0101]),
    ( 27 => [0b1111_1111, 0b1111_1111, 0b1111_1101, 0b0000_0110]),
    ( 27 => [0b1111_1111, 0b1111_1111, 0b1111_1101, 0b0000_0111]),
    ( 27 => [0b1111_1111, 0b1111_1111, 0b1111_1110, 0b0000_0000]),
    ( 26 => [0b1111_1111, 0b1111_1111, 0b1111_1011, 0b0000_0010]),
];

pub trait HpackStringEncode {
    fn hpack_encode(&self) -> Result<Vec<u8>, Error>;
}

impl HpackStringEncode for Vec<u8> {
    fn hpack_encode(&self) -> Result<Vec<u8>, Error> {
        let mut encoder = HuffmanEncoder::new();
        for code in self {
            encoder.put(*code)?;
        }
        encoder.ends()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_set_bits() {
        let mut buf = [0b1111_1111; 16];
        let mut pos = BitWindow::default();

        // Write a full 8 bits into a single byte
        pos.count = 8;
        write_bits(&mut buf, &pos, 0b1_0101);
        assert_eq!(&buf[..1], &[0b1_0101]);
        pos.byte += 1;

        // 7-bit byte-spanning writes at each possible bit offset
        pos.count = 7;
        for _ in 0..8 {
            write_bits(&mut buf, &pos, 0b101_0101);
            pos.forwards(7);
        }
        assert_eq!(
            &buf[1..8],
            &[
                0b1010_1011,
                0b0101_0110,
                0b1010_1101,
                0b0101_1010,
                0b1011_0101,
                0b0110_1010,
                0b1101_0101
            ]
        );

        // Single-write partial bits, aligned with byte start
        pos.count = 5;
        write_bits(&mut buf, &pos, 0b1_0101);
        assert_eq!(&buf[8..9], &[0b1010_1111]);
    }

    macro_rules! encoding {
        [ $( $code:expr => $( $byte:expr ),* ; )* ] => { $( {
            let bytes = vec![$( $byte ),*];
            let res = vec![ $code ].hpack_encode();
            assert_eq!(res, Ok(bytes), "fail to encode {}", $code);
        } )* }
    }

    /**
     * https://tools.ietf.org/html/rfc7541
     * Appendix B.  Huffman Code
     */
    #[test]
    #[allow(clippy::cognitive_complexity)]
    fn test_encode_single_value() {
        encoding![
             48 => (0b0000_0000 << 3) | /* padding */ 0b0000_0111; // '0'
             49 => (0b0000_0001 << 3) | /* padding */ 0b0000_0111; // '1'
             50 => (0b0000_0010 << 3) | /* padding */ 0b0000_0111; // '2'
             97 => (0b0000_0011 << 3) | /* padding */ 0b0000_0111; // 'a'
             99 => (0b0000_0100 << 3) | /* padding */ 0b0000_0111; // 'c'
            101 => (0b0000_0101 << 3) | /* padding */ 0b0000_0111; // 'e'
            105 => (0b0000_0110 << 3) | /* padding */ 0b0000_0111; // 'i'
            111 => (0b0000_0111 << 3) | /* padding */ 0b0000_0111; // 'o'
            115 => (0b0000_1000 << 3) | /* padding */ 0b0000_0111; // 's'
            116 => (0b0000_1001 << 3) | /* padding */ 0b0000_0111; // 't'
             32 => (0b0001_0100 << 2) | /* padding */ 0b0000_0011;
             37 => (0b0001_0101 << 2) | /* padding */ 0b0000_0011; // '%'
             45 => (0b0001_0110 << 2) | /* padding */ 0b0000_0011; // '-'
             46 => (0b0001_0111 << 2) | /* padding */ 0b0000_0011; // '.'
             47 => (0b0001_1000 << 2) | /* padding */ 0b0000_0011; // '/'
             51 => (0b0001_1001 << 2) | /* padding */ 0b0000_0011; // '3'
             52 => (0b0001_1010 << 2) | /* padding */ 0b0000_0011; // '4'
             53 => (0b0001_1011 << 2) | /* padding */ 0b0000_0011; // '5'
             54 => (0b0001_1100 << 2) | /* padding */ 0b0000_0011; // '6'
             55 => (0b0001_1101 << 2) | /* padding */ 0b0000_0011; // '7'
             56 => (0b0001_1110 << 2) | /* padding */ 0b0000_0011; // '8'
             57 => (0b0001_1111 << 2) | /* padding */ 0b0000_0011; // '9'
             61 => (0b0010_0000 << 2) | /* padding */ 0b0000_0011; // '='
             65 => (0b0010_0001 << 2) | /* padding */ 0b0000_0011; // 'A'
             95 => (0b0010_0010 << 2) | /* padding */ 0b0000_0011; // '_'
             98 => (0b0010_0011 << 2) | /* padding */ 0b0000_0011; // 'b'
            100 => (0b0010_0100 << 2) | /* padding */ 0b0000_0011; // 'd'
            102 => (0b0010_0101 << 2) | /* padding */ 0b0000_0011; // 'f'
            103 => (0b0010_0110 << 2) | /* padding */ 0b0000_0011; // 'g'
            104 => (0b0010_0111 << 2) | /* padding */ 0b0000_0011; // 'h'
            108 => (0b0010_1000 << 2) | /* padding */ 0b0000_0011; // 'l'
            109 => (0b0010_1001 << 2) | /* padding */ 0b0000_0011; // 'm'
            110 => (0b0010_1010 << 2) | /* padding */ 0b0000_0011; // 'n'
            112 => (0b0010_1011 << 2) | /* padding */ 0b0000_0011; // 'p'
            114 => (0b0010_1100 << 2) | /* padding */ 0b0000_0011; // 'r'
            117 => (0b0010_1101 << 2) | /* padding */ 0b0000_0011; // 'u'
             58 => (0b0101_1100 << 1) | /* padding */ 0b0000_0001; // ':'
             66 => (0b0101_1101 << 1) | /* padding */ 0b0000_0001; // 'B'
             67 => (0b0101_1110 << 1) | /* padding */ 0b0000_0001; // 'C'
             68 => (0b0101_1111 << 1) | /* padding */ 0b0000_0001; // 'D'
             69 => (0b0110_0000 << 1) | /* padding */ 0b0000_0001; // 'E'
             70 => (0b0110_0001 << 1) | /* padding */ 0b0000_0001; // 'F'
             71 => (0b0110_0010 << 1) | /* padding */ 0b0000_0001; // 'G'
             72 => (0b0110_0011 << 1) | /* padding */ 0b0000_0001; // 'H'
             73 => (0b0110_0100 << 1) | /* padding */ 0b0000_0001; // 'I'
             74 => (0b0110_0101 << 1) | /* padding */ 0b0000_0001; // 'J'
             75 => (0b0110_0110 << 1) | /* padding */ 0b0000_0001; // 'K'
             76 => (0b0110_0111 << 1) | /* padding */ 0b0000_0001; // 'L'
             77 => (0b0110_1000 << 1) | /* padding */ 0b0000_0001; // 'M'
             78 => (0b0110_1001 << 1) | /* padding */ 0b0000_0001; // 'N'
             79 => (0b0110_1010 << 1) | /* padding */ 0b0000_0001; // 'O'
             80 => (0b0110_1011 << 1) | /* padding */ 0b0000_0001; // 'P'
             81 => (0b0110_1100 << 1) | /* padding */ 0b0000_0001; // 'Q'
             82 => (0b0110_1101 << 1) | /* padding */ 0b0000_0001; // 'R'
             83 => (0b0110_1110 << 1) | /* padding */ 0b0000_0001; // 'S'
             84 => (0b0110_1111 << 1) | /* padding */ 0b0000_0001; // 'T'
             85 => (0b0111_0000 << 1) | /* padding */ 0b0000_0001; // 'U'
             86 => (0b0111_0001 << 1) | /* padding */ 0b0000_0001; // 'V'
             87 => (0b0111_0010 << 1) | /* padding */ 0b0000_0001; // 'W'
             89 => (0b0111_0011 << 1) | /* padding */ 0b0000_0001; // 'Y'
            106 => (0b0111_0100 << 1) | /* padding */ 0b0000_0001; // 'j'
            107 => (0b0111_0101 << 1) | /* padding */ 0b0000_0001; // 'k'
            113 => (0b0111_0110 << 1) | /* padding */ 0b0000_0001; // 'q'
            118 => (0b0111_0111 << 1) | /* padding */ 0b0000_0001; // 'v'
            119 => (0b0111_1000 << 1) | /* padding */ 0b0000_0001; // 'w'
            120 => (0b0111_1001 << 1) | /* padding */ 0b0000_0001; // 'x'
            121 => (0b0111_1010 << 1) | /* padding */ 0b0000_0001; // 'y'
            122 => (0b0111_1011 << 1) | /* padding */ 0b0000_0001; // 'z'
             38 => 0b1111_1000; // '&'
             42 => 0b1111_1001; // '*'
             44 => 0b1111_1010; // ','
             59 => 0b1111_1011;
             88 => 0b1111_1100; // 'X'
             90 => 0b1111_1101; // 'Z'
             33 => 0b1111_1110, (0b0000_0000 << 6) | /* padding */ 0b0011_1111; // '!'
             34 => 0b1111_1110, (0b0000_0001 << 6) | /* padding */ 0b0011_1111; // '"'
             40 => 0b1111_1110, (0b0000_0010 << 6) | /* padding */ 0b0011_1111; // '('
             41 => 0b1111_1110, (0b0000_0011 << 6) | /* padding */ 0b0011_1111; // ')'
             63 => 0b1111_1111, (0b0000_0000 << 6) | /* padding */ 0b0011_1111; // '?'
             39 => 0b1111_1111, (0b0000_0010 << 5) | /* padding */ 0b0001_1111; // '''
             43 => 0b1111_1111, (0b0000_0011 << 5) | /* padding */ 0b0001_1111; // '+'
            124 => 0b1111_1111, (0b0000_0100 << 5) | /* padding */ 0b0001_1111; // '|'
             35 => 0b1111_1111, (0b0000_1010 << 4) | /* padding */ 0b0000_1111; // '#'
             62 => 0b1111_1111, (0b0000_1011 << 4) | /* padding */ 0b0000_1111; // '>'
              0 => 0b1111_1111, (0b0001_1000 << 3) | /* padding */ 0b0000_0111;
             36 => 0b1111_1111, (0b0001_1001 << 3) | /* padding */ 0b0000_0111; // '$'
             64 => 0b1111_1111, (0b0001_1010 << 3) | /* padding */ 0b0000_0111; // '@'
             91 => 0b1111_1111, (0b0001_1011 << 3) | /* padding */ 0b0000_0111; // '['
             93 => 0b1111_1111, (0b0001_1100 << 3) | /* padding */ 0b0000_0111; // ']'
            126 => 0b1111_1111, (0b0001_1101 << 3) | /* padding */ 0b0000_0111; // '~'
             94 => 0b1111_1111, (0b0011_1100 << 2) | /* padding */ 0b0000_0011; // '^'
            125 => 0b1111_1111, (0b0011_1101 << 2) | /* padding */ 0b0000_0011; // '}'
             60 => 0b1111_1111, (0b0111_1100 << 1) | /* padding */ 0b0000_0001; // '<'
             96 => 0b1111_1111, (0b0111_1101 << 1) | /* padding */ 0b0000_0001; // '`'
            123 => 0b1111_1111, (0b0111_1110 << 1) | /* padding */ 0b0000_0001; // '{'
             92 => 0b1111_1111, 0b1111_1110, (0b0000_0000 << 5) | /* padding */ 0b0001_1111; // '\'
            195 => 0b1111_1111, 0b1111_1110, (0b0000_0001 << 5) | /* padding */ 0b0001_1111;
            208 => 0b1111_1111, 0b1111_1110, (0b0000_0010 << 5) | /* padding */ 0b0001_1111;
            128 => 0b1111_1111, 0b1111_1110, (0b0000_0110 << 4) | /* padding */ 0b0000_1111;
            130 => 0b1111_1111, 0b1111_1110, (0b0000_0111 << 4) | /* padding */ 0b0000_1111;
            131 => 0b1111_1111, 0b1111_1110, (0b0000_1000 << 4) | /* padding */ 0b0000_1111;
            162 => 0b1111_1111, 0b1111_1110, (0b0000_1001 << 4) | /* padding */ 0b0000_1111;
            184 => 0b1111_1111, 0b1111_1110, (0b0000_1010 << 4) | /* padding */ 0b0000_1111;
            194 => 0b1111_1111, 0b1111_1110, (0b0000_1011 << 4) | /* padding */ 0b0000_1111;
            224 => 0b1111_1111, 0b1111_1110, (0b0000_1100 << 4) | /* padding */ 0b0000_1111;
            226 => 0b1111_1111, 0b1111_1110, (0b0000_1101 << 4) | /* padding */ 0b0000_1111;
            153 => 0b1111_1111, 0b1111_1110, (0b0001_1100 << 3) | /* padding */ 0b0000_0111;
            161 => 0b1111_1111, 0b1111_1110, (0b0001_1101 << 3) | /* padding */ 0b0000_0111;
            167 => 0b1111_1111, 0b1111_1110, (0b0001_1110 << 3) | /* padding */ 0b0000_0111;
            172 => 0b1111_1111, 0b1111_1110, (0b0001_1111 << 3) | /* padding */ 0b0000_0111;
            176 => 0b1111_1111, 0b1111_1111, (0b0000_0000 << 3) | /* padding */ 0b0000_0111;
            177 => 0b1111_1111, 0b1111_1111, (0b0000_0001 << 3) | /* padding */ 0b0000_0111;
            179 => 0b1111_1111, 0b1111_1111, (0b0000_0010 << 3) | /* padding */ 0b0000_0111;
            209 => 0b1111_1111, 0b1111_1111, (0b0000_0011 << 3) | /* padding */ 0b0000_0111;
            216 => 0b1111_1111, 0b1111_1111, (0b0000_0100 << 3) | /* padding */ 0b0000_0111;
            217 => 0b1111_1111, 0b1111_1111, (0b0000_0101 << 3) | /* padding */ 0b0000_0111;
            227 => 0b1111_1111, 0b1111_1111, (0b0000_0110 << 3) | /* padding */ 0b0000_0111;
            229 => 0b1111_1111, 0b1111_1111, (0b0000_0111 << 3) | /* padding */ 0b0000_0111;
            230 => 0b1111_1111, 0b1111_1111, (0b0000_1000 << 3) | /* padding */ 0b0000_0111;
            129 => 0b1111_1111, 0b1111_1111, (0b0001_0010 << 2) | /* padding */ 0b0000_0011;
            132 => 0b1111_1111, 0b1111_1111, (0b0001_0011 << 2) | /* padding */ 0b0000_0011;
            133 => 0b1111_1111, 0b1111_1111, (0b0001_0100 << 2) | /* padding */ 0b0000_0011;
            134 => 0b1111_1111, 0b1111_1111, (0b0001_0101 << 2) | /* padding */ 0b0000_0011;
            136 => 0b1111_1111, 0b1111_1111, (0b0001_0110 << 2) | /* padding */ 0b0000_0011;
            146 => 0b1111_1111, 0b1111_1111, (0b0001_0111 << 2) | /* padding */ 0b0000_0011;
            154 => 0b1111_1111, 0b1111_1111, (0b0001_1000 << 2) | /* padding */ 0b0000_0011;
            156 => 0b1111_1111, 0b1111_1111, (0b0001_1001 << 2) | /* padding */ 0b0000_0011;
            160 => 0b1111_1111, 0b1111_1111, (0b0001_1010 << 2) | /* padding */ 0b0000_0011;
            163 => 0b1111_1111, 0b1111_1111, (0b0001_1011 << 2) | /* padding */ 0b0000_0011;
            164 => 0b1111_1111, 0b1111_1111, (0b0001_1100 << 2) | /* padding */ 0b0000_0011;
            169 => 0b1111_1111, 0b1111_1111, (0b0001_1101 << 2) | /* padding */ 0b0000_0011;
            170 => 0b1111_1111, 0b1111_1111, (0b0001_1110 << 2) | /* padding */ 0b0000_0011;
            173 => 0b1111_1111, 0b1111_1111, (0b0001_1111 << 2) | /* padding */ 0b0000_0011;
            178 => 0b1111_1111, 0b1111_1111, (0b0010_0000 << 2) | /* padding */ 0b0000_0011;
            181 => 0b1111_1111, 0b1111_1111, (0b0010_0001 << 2) | /* padding */ 0b0000_0011;
            185 => 0b1111_1111, 0b1111_1111, (0b0010_0010 << 2) | /* padding */ 0b0000_0011;
            186 => 0b1111_1111, 0b1111_1111, (0b0010_0011 << 2) | /* padding */ 0b0000_0011;
            187 => 0b1111_1111, 0b1111_1111, (0b0010_0100 << 2) | /* padding */ 0b0000_0011;
            189 => 0b1111_1111, 0b1111_1111, (0b0010_0101 << 2) | /* padding */ 0b0000_0011;
            190 => 0b1111_1111, 0b1111_1111, (0b0010_0110 << 2) | /* padding */ 0b0000_0011;
            196 => 0b1111_1111, 0b1111_1111, (0b0010_0111 << 2) | /* padding */ 0b0000_0011;
            198 => 0b1111_1111, 0b1111_1111, (0b0010_1000 << 2) | /* padding */ 0b0000_0011;
            228 => 0b1111_1111, 0b1111_1111, (0b0010_1001 << 2) | /* padding */ 0b0000_0011;
            232 => 0b1111_1111, 0b1111_1111, (0b0010_1010 << 2) | /* padding */ 0b0000_0011;
            233 => 0b1111_1111, 0b1111_1111, (0b0010_1011 << 2) | /* padding */ 0b0000_0011;
              1 => 0b1111_1111, 0b1111_1111, (0b0101_1000 << 1) | /* padding */ 0b0000_0001;
            135 => 0b1111_1111, 0b1111_1111, (0b0101_1001 << 1) | /* padding */ 0b0000_0001;
            137 => 0b1111_1111, 0b1111_1111, (0b0101_1010 << 1) | /* padding */ 0b0000_0001;
            138 => 0b1111_1111, 0b1111_1111, (0b0101_1011 << 1) | /* padding */ 0b0000_0001;
            139 => 0b1111_1111, 0b1111_1111, (0b0101_1100 << 1) | /* padding */ 0b0000_0001;
            140 => 0b1111_1111, 0b1111_1111, (0b0101_1101 << 1) | /* padding */ 0b0000_0001;
            141 => 0b1111_1111, 0b1111_1111, (0b0101_1110 << 1) | /* padding */ 0b0000_0001;
            143 => 0b1111_1111, 0b1111_1111, (0b0101_1111 << 1) | /* padding */ 0b0000_0001;
            147 => 0b1111_1111, 0b1111_1111, (0b0110_0000 << 1) | /* padding */ 0b0000_0001;
            149 => 0b1111_1111, 0b1111_1111, (0b0110_0001 << 1) | /* padding */ 0b0000_0001;
            150 => 0b1111_1111, 0b1111_1111, (0b0110_0010 << 1) | /* padding */ 0b0000_0001;
            151 => 0b1111_1111, 0b1111_1111, (0b0110_0011 << 1) | /* padding */ 0b0000_0001;
            152 => 0b1111_1111, 0b1111_1111, (0b0110_0100 << 1) | /* padding */ 0b0000_0001;
            155 => 0b1111_1111, 0b1111_1111, (0b0110_0101 << 1) | /* padding */ 0b0000_0001;
            157 => 0b1111_1111, 0b1111_1111, (0b0110_0110 << 1) | /* padding */ 0b0000_0001;
            158 => 0b1111_1111, 0b1111_1111, (0b0110_0111 << 1) | /* padding */ 0b0000_0001;
            165 => 0b1111_1111, 0b1111_1111, (0b0110_1000 << 1) | /* padding */ 0b0000_0001;
            166 => 0b1111_1111, 0b1111_1111, (0b0110_1001 << 1) | /* padding */ 0b0000_0001;
            168 => 0b1111_1111, 0b1111_1111, (0b0110_1010 << 1) | /* padding */ 0b0000_0001;
            174 => 0b1111_1111, 0b1111_1111, (0b0110_1011 << 1) | /* padding */ 0b0000_0001;
            175 => 0b1111_1111, 0b1111_1111, (0b0110_1100 << 1) | /* padding */ 0b0000_0001;
            180 => 0b1111_1111, 0b1111_1111, (0b0110_1101 << 1) | /* padding */ 0b0000_0001;
            182 => 0b1111_1111, 0b1111_1111, (0b0110_1110 << 1) | /* padding */ 0b0000_0001;
            183 => 0b1111_1111, 0b1111_1111, (0b0110_1111 << 1) | /* padding */ 0b0000_0001;
            188 => 0b1111_1111, 0b1111_1111, (0b0111_0000 << 1) | /* padding */ 0b0000_0001;
            191 => 0b1111_1111, 0b1111_1111, (0b0111_0001 << 1) | /* padding */ 0b0000_0001;
            197 => 0b1111_1111, 0b1111_1111, (0b0111_0010 << 1) | /* padding */ 0b0000_0001;
            231 => 0b1111_1111, 0b1111_1111, (0b0111_0011 << 1) | /* padding */ 0b0000_0001;
            239 => 0b1111_1111, 0b1111_1111, (0b0111_0100 << 1) | /* padding */ 0b0000_0001;
              9 => 0b1111_1111, 0b1111_1111, 0b1110_1010;
            142 => 0b1111_1111, 0b1111_1111, 0b1110_1011;
            144 => 0b1111_1111, 0b1111_1111, 0b1110_1100;
            145 => 0b1111_1111, 0b1111_1111, 0b1110_1101;
            148 => 0b1111_1111, 0b1111_1111, 0b1110_1110;
            159 => 0b1111_1111, 0b1111_1111, 0b1110_1111;
            171 => 0b1111_1111, 0b1111_1111, 0b1111_0000;
            206 => 0b1111_1111, 0b1111_1111, 0b1111_0001;
            215 => 0b1111_1111, 0b1111_1111, 0b1111_0010;
            225 => 0b1111_1111, 0b1111_1111, 0b1111_0011;
            236 => 0b1111_1111, 0b1111_1111, 0b1111_0100;
            237 => 0b1111_1111, 0b1111_1111, 0b1111_0101;
            199 => 0b1111_1111, 0b1111_1111, 0b1111_0110, (0b0000_0000 << 7) | /* padding */ 0b0111_1111;
            207 => 0b1111_1111, 0b1111_1111, 0b1111_0110, (0b0000_0001 << 7) | /* padding */ 0b0111_1111;
            234 => 0b1111_1111, 0b1111_1111, 0b1111_0111, (0b0000_0000 << 7) | /* padding */ 0b0111_1111;
            235 => 0b1111_1111, 0b1111_1111, 0b1111_0111, (0b0000_0001 << 7) | /* padding */ 0b0111_1111;
            192 => 0b1111_1111, 0b1111_1111, 0b1111_1000, (0b0000_0000 << 6) | /* padding */ 0b0011_1111;
            193 => 0b1111_1111, 0b1111_1111, 0b1111_1000, (0b0000_0001 << 6) | /* padding */ 0b0011_1111;
            200 => 0b1111_1111, 0b1111_1111, 0b1111_1000, (0b0000_0010 << 6) | /* padding */ 0b0011_1111;
            201 => 0b1111_1111, 0b1111_1111, 0b1111_1000, (0b0000_0011 << 6) | /* padding */ 0b0011_1111;
            202 => 0b1111_1111, 0b1111_1111, 0b1111_1001, (0b0000_0000 << 6) | /* padding */ 0b0011_1111;
            205 => 0b1111_1111, 0b1111_1111, 0b1111_1001, (0b0000_0001 << 6) | /* padding */ 0b0011_1111;
            210 => 0b1111_1111, 0b1111_1111, 0b1111_1001, (0b0000_0010 << 6) | /* padding */ 0b0011_1111;
            213 => 0b1111_1111, 0b1111_1111, 0b1111_1001, (0b0000_0011 << 6) | /* padding */ 0b0011_1111;
            218 => 0b1111_1111, 0b1111_1111, 0b1111_1010, (0b0000_0000 << 6) | /* padding */ 0b0011_1111;
            219 => 0b1111_1111, 0b1111_1111, 0b1111_1010, (0b0000_0001 << 6) | /* padding */ 0b0011_1111;
            238 => 0b1111_1111, 0b1111_1111, 0b1111_1010, (0b0000_0010 << 6) | /* padding */ 0b0011_1111;
            240 => 0b1111_1111, 0b1111_1111, 0b1111_1010, (0b0000_0011 << 6) | /* padding */ 0b0011_1111;
            242 => 0b1111_1111, 0b1111_1111, 0b1111_1011, (0b0000_0000 << 6) | /* padding */ 0b0011_1111;
            243 => 0b1111_1111, 0b1111_1111, 0b1111_1011, (0b0000_0001 << 6) | /* padding */ 0b0011_1111;
            255 => 0b1111_1111, 0b1111_1111, 0b1111_1011, (0b0000_0010 << 6) | /* padding */ 0b0011_1111;
            203 => 0b1111_1111, 0b1111_1111, 0b1111_1011, (0b0000_0110 << 5) | /* padding */ 0b0001_1111;
            204 => 0b1111_1111, 0b1111_1111, 0b1111_1011, (0b0000_0111 << 5) | /* padding */ 0b0001_1111;
            211 => 0b1111_1111, 0b1111_1111, 0b1111_1100, (0b0000_0000 << 5) | /* padding */ 0b0001_1111;
            212 => 0b1111_1111, 0b1111_1111, 0b1111_1100, (0b0000_0001 << 5) | /* padding */ 0b0001_1111;
            214 => 0b1111_1111, 0b1111_1111, 0b1111_1100, (0b0000_0010 << 5) | /* padding */ 0b0001_1111;
            221 => 0b1111_1111, 0b1111_1111, 0b1111_1100, (0b0000_0011 << 5) | /* padding */ 0b0001_1111;
            222 => 0b1111_1111, 0b1111_1111, 0b1111_1100, (0b0000_0100 << 5) | /* padding */ 0b0001_1111;
            223 => 0b1111_1111, 0b1111_1111, 0b1111_1100, (0b0000_0101 << 5) | /* padding */ 0b0001_1111;
            241 => 0b1111_1111, 0b1111_1111, 0b1111_1100, (0b0000_0110 << 5) | /* padding */ 0b0001_1111;
            244 => 0b1111_1111, 0b1111_1111, 0b1111_1100, (0b0000_0111 << 5) | /* padding */ 0b0001_1111;
            245 => 0b1111_1111, 0b1111_1111, 0b1111_1101, (0b0000_0000 << 5) | /* padding */ 0b0001_1111;
            246 => 0b1111_1111, 0b1111_1111, 0b1111_1101, (0b0000_0001 << 5) | /* padding */ 0b0001_1111;
            247 => 0b1111_1111, 0b1111_1111, 0b1111_1101, (0b0000_0010 << 5) | /* padding */ 0b0001_1111;
            248 => 0b1111_1111, 0b1111_1111, 0b1111_1101, (0b0000_0011 << 5) | /* padding */ 0b0001_1111;
            250 => 0b1111_1111, 0b1111_1111, 0b1111_1101, (0b0000_0100 << 5) | /* padding */ 0b0001_1111;
            251 => 0b1111_1111, 0b1111_1111, 0b1111_1101, (0b0000_0101 << 5) | /* padding */ 0b0001_1111;
            252 => 0b1111_1111, 0b1111_1111, 0b1111_1101, (0b0000_0110 << 5) | /* padding */ 0b0001_1111;
            253 => 0b1111_1111, 0b1111_1111, 0b1111_1101, (0b0000_0111 << 5) | /* padding */ 0b0001_1111;
            254 => 0b1111_1111, 0b1111_1111, 0b1111_1110, (0b0000_0000 << 5) | /* padding */ 0b0001_1111;
              2 => 0b1111_1111, 0b1111_1111, 0b1111_1110, (0b0000_0010 << 4) | /* padding */ 0b0000_1111;
              3 => 0b1111_1111, 0b1111_1111, 0b1111_1110, (0b0000_0011 << 4) | /* padding */ 0b0000_1111;
              4 => 0b1111_1111, 0b1111_1111, 0b1111_1110, (0b0000_0100 << 4) | /* padding */ 0b0000_1111;
              5 => 0b1111_1111, 0b1111_1111, 0b1111_1110, (0b0000_0101 << 4) | /* padding */ 0b0000_1111;
              6 => 0b1111_1111, 0b1111_1111, 0b1111_1110, (0b0000_0110 << 4) | /* padding */ 0b0000_1111;
              7 => 0b1111_1111, 0b1111_1111, 0b1111_1110, (0b0000_0111 << 4) | /* padding */ 0b0000_1111;
              8 => 0b1111_1111, 0b1111_1111, 0b1111_1110, (0b0000_1000 << 4) | /* padding */ 0b0000_1111;
             11 => 0b1111_1111, 0b1111_1111, 0b1111_1110, (0b0000_1001 << 4) | /* padding */ 0b0000_1111;
             12 => 0b1111_1111, 0b1111_1111, 0b1111_1110, (0b0000_1010 << 4) | /* padding */ 0b0000_1111;
             14 => 0b1111_1111, 0b1111_1111, 0b1111_1110, (0b0000_1011 << 4) | /* padding */ 0b0000_1111;
             15 => 0b1111_1111, 0b1111_1111, 0b1111_1110, (0b0000_1100 << 4) | /* padding */ 0b0000_1111;
             16 => 0b1111_1111, 0b1111_1111, 0b1111_1110, (0b0000_1101 << 4) | /* padding */ 0b0000_1111;
             17 => 0b1111_1111, 0b1111_1111, 0b1111_1110, (0b0000_1110 << 4) | /* padding */ 0b0000_1111;
             18 => 0b1111_1111, 0b1111_1111, 0b1111_1110, (0b0000_1111 << 4) | /* padding */ 0b0000_1111;
             19 => 0b1111_1111, 0b1111_1111, 0b1111_1111, (0b0000_0000 << 4) | /* padding */ 0b0000_1111;
             20 => 0b1111_1111, 0b1111_1111, 0b1111_1111, (0b0000_0001 << 4) | /* padding */ 0b0000_1111;
             21 => 0b1111_1111, 0b1111_1111, 0b1111_1111, (0b0000_0010 << 4) | /* padding */ 0b0000_1111;
             23 => 0b1111_1111, 0b1111_1111, 0b1111_1111, (0b0000_0011 << 4) | /* padding */ 0b0000_1111;
             24 => 0b1111_1111, 0b1111_1111, 0b1111_1111, (0b0000_0100 << 4) | /* padding */ 0b0000_1111;
             25 => 0b1111_1111, 0b1111_1111, 0b1111_1111, (0b0000_0101 << 4) | /* padding */ 0b0000_1111;
             26 => 0b1111_1111, 0b1111_1111, 0b1111_1111, (0b0000_0110 << 4) | /* padding */ 0b0000_1111;
             27 => 0b1111_1111, 0b1111_1111, 0b1111_1111, (0b0000_0111 << 4) | /* padding */ 0b0000_1111;
             28 => 0b1111_1111, 0b1111_1111, 0b1111_1111, (0b0000_1000 << 4) | /* padding */ 0b0000_1111;
             29 => 0b1111_1111, 0b1111_1111, 0b1111_1111, (0b0000_1001 << 4) | /* padding */ 0b0000_1111;
             30 => 0b1111_1111, 0b1111_1111, 0b1111_1111, (0b0000_1010 << 4) | /* padding */ 0b0000_1111;
             31 => 0b1111_1111, 0b1111_1111, 0b1111_1111, (0b0000_1011 << 4) | /* padding */ 0b0000_1111;
            127 => 0b1111_1111, 0b1111_1111, 0b1111_1111, (0b0000_1100 << 4) | /* padding */ 0b0000_1111;
            220 => 0b1111_1111, 0b1111_1111, 0b1111_1111, (0b0000_1101 << 4) | /* padding */ 0b0000_1111;
            249 => 0b1111_1111, 0b1111_1111, 0b1111_1111, (0b0000_1110 << 4) | /* padding */ 0b0000_1111;
             10 => 0b1111_1111, 0b1111_1111, 0b1111_1111, (0b0011_1100 << 2) | /* padding */ 0b0000_0011;
             13 => 0b1111_1111, 0b1111_1111, 0b1111_1111, (0b0011_1101 << 2) | /* padding */ 0b0000_0011;
             22 => 0b1111_1111, 0b1111_1111, 0b1111_1111, (0b0011_1110 << 2) | /* padding */ 0b0000_0011;
        ];
    }

    /**
     * https://tools.ietf.org/html/rfc7541
     * Appendix B.  Huffman Code
     */
    #[test]
    fn test_encode_all_code_joined() {
        let bytes = vec![
            // 0     |11111111|11000
            0b1111_1111,
            (0b0001_1000 << 3)
                // 1     |11111111|11111111|1011000
                + 0b0000_0111,
            0b1111_1111,
            0b1111_1101,
            (0b0000_1000 << 4)
                // 2     |11111111|11111111|11111110|0010
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            0b1110_0010,
            // 3     |11111111|11111111|11111110|0011
            0b1111_1111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_0011 << 4)
                // 4     |11111111|11111111|11111110|0100
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            0b1110_0100,
            // 5     |11111111|11111111|11111110|0101
            0b1111_1111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_0101 << 4)
                // 6     |11111111|11111111|11111110|0110
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            0b1110_0110,
            // 7     |11111111|11111111|11111110|0111
            0b1111_1111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_0111 << 4)
                // 8     |11111111|11111111|11111110|1000
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            0b1110_1000,
            // 9     |11111111|11111111|11101010
            0b1111_1111,
            0b1111_1111,
            0b1110_1010,
            // 10     |11111111|11111111|11111111|111100
            0b1111_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0011_1100 << 2)
                // 11     |11111111|11111111|11111110|1001
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1111,
            0b1111_1010,
            (0b0000_0001 << 6)
                // 12     |11111111|11111111|11111110|1010
                + 0b0011_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0010_1010 << 2)
                // 13     |11111111|11111111|11111111|111101
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0000_1101 << 4)
                // 14     |11111111|11111111|11111110|1011
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            0b1110_1011,
            // 15     |11111111|11111111|11111110|1100
            0b1111_1111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_1100 << 4)
                // 16     |11111111|11111111|11111110|1101
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            0b1110_1101,
            // 17     |11111111|11111111|11111110|1110
            0b1111_1111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_1110 << 4)
                // 18     |11111111|11111111|11111110|1111
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            0b1110_1111,
            // 19     |11111111|11111111|11111111|0000
            0b1111_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0000_0000 << 4)
                // 20     |11111111|11111111|11111111|0001
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            0b1111_0001,
            // 21     |11111111|11111111|11111111|0010
            0b1111_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0000_0010 << 4)
                // 22     |11111111|11111111|11111111|111110
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0000_0010 << 6)
                // 23     |11111111|11111111|11111111|0011
                + 0b0011_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0011_0011 << 2)
                // 24     |11111111|11111111|11111111|0100
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1111,
            0b1111_1101,
            (0b0000_0000 << 6)
                // 25     |11111111|11111111|11111111|0101
                + 0b0011_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0011_0101 << 2)
                // 26     |11111111|11111111|11111111|0110
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1111,
            0b1111_1101,
            (0b0000_0010 << 6)
                // 27     |11111111|11111111|11111111|0111
                + 0b0011_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0011_0111 << 2)
                // 28     |11111111|11111111|11111111|1000
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_0000 << 6)
                // 29     |11111111|11111111|11111111|1001
                + 0b0011_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0011_1001 << 2)
                // 30     |11111111|11111111|11111111|1010
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_0010 << 6)
                // 31     |11111111|11111111|11111111|1011
                + 0b0011_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0011_1011 << 2)
                // 32     |010100
                + 0b0000_0001,
            (0b0000_0100 << 4)
                // 33 -!- |11111110|00
                + 0b0000_1111,
            (0b0011_1000 << 2)
                // 34 -;- |11111110|01
                + 0b0000_0011,
            0b1111_1001,
            // 35 -#- |11111111|1010
            0b1111_1111,
            (0b0000_1010 << 4)
                // 36 -$- |11111111|11001
                + 0b0000_1111,
            0b1111_1100,
            (0b0000_0001 << 7)
                // 37 -%- |010101
                + (0b0001_0101 << 1)
                // 38 -&- |11111000
                + 0b0000_0001,
            (0b0111_1000 << 1)
                // 39 -'- |11111111|010
                + 0b0000_0001,
            0b1111_1110,
            (0b0000_0010 << 6)
                // 40 -(- |11111110|10
                + 0b0011_1111,
            (0b0000_1010 << 4)
                // 41 -)- |11111110|11
                + 0b0000_1111,
            (0b0011_1011 << 2)
                // 42 -*- |11111001
                + 0b0000_0011,
            (0b0011_1001 << 2)
                // 43 -+- |11111111|011
                + 0b0000_0011,
            0b1111_1101,
            (0b0000_0001 << 7)
                // 44 -,- |11111010
                + 0b0111_1101,
            (0b0000_0000 << 7)
                // 45 --- |010110
                + (0b0001_0110 << 1)
                // 46 -.- |010111
                + 0b0000_0000,
            (0b0001_0111 << 3)
                // 47 -/- |011000
                + 0b0000_0011,
            (0b0000_0000 << 5)
                // 48 -0- |00000
                + 0b0000_0000,
            // 49 -1- |00001
            (0b0000_0001 << 3)
                // 50 -2- |00010
                + 0b0000_0000,
            (0b0000_0010 << 6)
                // 51 -3- |011001
                + 0b0001_1001,
            // 52 -4- |011010
            (0b0001_1010 << 2)
                // 53 -5- |011011
                + 0b0000_0001,
            (0b0000_1011 << 4)
                // 54 -6- |011100
                + 0b0000_0111,
            (0b0000_0000 << 6)
                // 55 -7- |011101
                + 0b0001_1101,
            // 56 -8- |011110
            (0b0001_1110 << 2)
                // 57 -9- |011111
                + 0b0000_0001,
            (0b0000_1111 << 4)
                // 58 -:- |1011100
                + 0b0000_1011,
            (0b0000_0100 << 5)
                // 59     |11111011
                + 0b0001_1111,
            (0b0000_0011 << 5)
                // 60 -<- |11111111|1111100
                + 0b0001_1111,
            0b1111_1111,
            (0b0000_0000 << 6)
                // 61 -=- |100000
                + 0b0010_0000,
            // 62 ->- |11111111|1011
            0b1111_1111,
            (0b0000_1011 << 4)
                // 63 -?- |11111111|00
                + 0b0000_1111,
            (0b0011_1100 << 2)
                // 64 -@- |11111111|11010
                + 0b0000_0011,
            0b1111_1111,
            (0b0000_0010 << 5)
                // 65 -A- |100001
                + 0b0001_0000,
            (0b0000_0001 << 7)
                // 66 -B- |1011101
                + 0b0101_1101,
            // 67 -C- |1011110
            (0b0101_1110 << 1)
                // 68 -D- |1011111
                + 0b0000_0001,
            (0b0001_1111 << 2)
                // 69 -E- |1100000
                + 0b0000_0011,
            (0b0000_0000 << 3)
                // 70 -F- |1100001
                + 0b0000_0110,
            (0b0000_0001 << 4)
                // 71 -G- |1100010
                + 0b0000_1100,
            (0b0000_0010 << 5)
                // 72 -H- |1100011
                + 0b0001_1000,
            (0b0000_0011 << 6)
                // 73 -I- |1100100
                + 0b0011_0010,
            (0b0000_0000 << 7)
                // 74 -J- |1100101
                + 0b0110_0101,
            // 75 -K- |1100110
            (0b0110_0110 << 1)
                // 76 -L- |1100111
                + 0b0000_0001,
            (0b0010_0111 << 2)
                // 77 -M- |1101000
                + 0b0000_0011,
            (0b0000_1000 << 3)
                // 78 -N- |1101001
                + 0b0000_0110,
            (0b0000_1001 << 4)
                // 79 -O- |1101010
                + 0b0000_1101,
            (0b0000_0010 << 5)
                // 80 -P- |1101011
                + 0b0001_1010,
            (0b0000_0011 << 6)
                // 81 -Q- |1101100
                + 0b0011_0110,
            (0b0000_0000 << 7)
                // 82 -R- |1101101
                + 0b0110_1101,
            // 83 -S- |1101110
            (0b0110_1110 << 1)
                // 84 -T- |1101111
                + 0b0000_0001,
            (0b0010_1111 << 2)
                // 85 -U- |1110000
                + 0b0000_0011,
            (0b0001_0000 << 3)
                // 86 -V- |1110001
                + 0b0000_0111,
            (0b0000_0001 << 4)
                // 87 -W- |1110010
                + 0b0000_1110,
            (0b0000_0010 << 5)
                // 88 -X- |11111100
                + 0b0001_1111,
            (0b0000_0100 << 5)
                // 89 -Y- |1110011
                + 0b0001_1100,
            (0b0000_0011 << 6)
                // 90 -Z- |11111101
                + 0b0011_1111,
            (0b0000_0001 << 6)
                // 91 -[- |11111111|11011
                + 0b0011_1111,
            (0b0111_1011 << 1)
                // 92 -\- |11111111|11111110|000
                + 0b0000_0001,
            0b1111_1111,
            0b1111_1100,
            (0b0000_0000 << 6)
                // 93 -]- |11111111|11100
                + 0b0011_1111,
            (0b0111_1100 << 1)
                // 94 -^- |11111111|111100
                + 0b0000_0001,
            0b1111_1111,
            (0b0001_1100 << 3)
                // 95 -_- |100010
                + 0b0000_0100,
            (0b0000_0010 << 5)
                // 96 -`- |11111111|1111101
                + 0b0001_1111,
            0b1111_1111,
            (0b0000_0001 << 6)
                // 97 -a- |00011
                + (0b0000_0011 << 1)
                // 98 -b- |100011
                + 0b0000_0001,
            (0b0000_0011 << 3)
                // 99 -c- |00100
                + 0b0000_0001,
            (0b0000_0000 << 6)
                // 100 -d- |100100
                + 0b0010_0100,
            // 101 -e- |00101
            (0b0000_0101 << 3)
                // 102 -f- |100101
                + 0b0000_0100,
            (0b0000_0101 << 5)
                // 103 -g- |100110
                + 0b0001_0011,
            (0b0000_0000 << 7)
                // 104 -h- |100111
                + (0b0010_0111 << 1)
                // 105 -i- |00110
                + 0b0000_0000,
            (0b0000_0110 << 4)
                // 106 -j- |1110100
                + 0b0000_1110,
            (0b0000_0100 << 5)
                // 107 -k- |1110101
                + 0b0001_1101,
            (0b0000_0001 << 6)
                // 108 -l- |101000
                + 0b0010_1000,
            // 109 -m- |101001
            (0b0010_1001 << 2)
                // 110 -n- |101010
                + 0b0000_0010,
            (0b0000_1010 << 4)
                // 111 -o- |00111
                + 0b0000_0011,
            (0b0000_0001 << 7)
                // 112 -p- |101011
                + (0b0010_1011 << 1)
                // 113 -q- |1110110
                + 0b0000_0001,
            (0b0011_0110 << 2)
                // 114 -r- |101100
                + 0b0000_0010,
            (0b0000_1100 << 4)
                // 115 -s- |01000
                + 0b0000_0100,
            (0b0000_0000 << 7)
                // 116 -t- |01001
                + (0b0000_1001 << 2)
                // 117 -u- |101101
                + 0b0000_0010,
            (0b0000_1101 << 4)
                // 118 -v- |1110111
                + 0b0000_1110,
            (0b0000_0111 << 5)
                // 119 -w- |1111000
                + 0b0001_1110,
            (0b0000_0000 << 6)
                // 120 -x- |1111001
                + 0b0011_1100,
            (0b0000_0001 << 7)
                // 121 -y- |1111010
                + 0b0111_1010,
            // 122 -z- |1111011
            (0b0111_1011 << 1)
                // 123 -{- |11111111|1111110
                + 0b0000_0001,
            0b1111_1111,
            (0b0011_1110 << 2)
                // 124 -|- |11111111|100
                + 0b0000_0011,
            0b1111_1110,
            (0b0000_0000 << 7)
                // 125 -}- |11111111|111101
                + 0b0111_1111,
            (0b0111_1101 << 1)
                // 126 -~- |11111111|11101
                + 0b0000_0001,
            0b1111_1111,
            (0b0000_1101 << 4)
                // 127     |11111111|11111111|11111111|1100
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            0b1111_1100,
            // 128     |11111111|11111110|0110
            0b1111_1111,
            0b1111_1110,
            (0b0000_0110 << 4)
                // 129     |11111111|11111111|010010
                + 0b0000_1111,
            0b1111_1111,
            0b1111_0100,
            (0b0000_0010 << 6)
                // 130     |11111111|11111110|0111
                + 0b0011_1111,
            0b1111_1111,
            (0b0010_0111 << 2)
                // 131     |11111111|11111110|1000
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1010,
            (0b0000_0000 << 6)
                // 132     |11111111|11111111|010011
                + 0b0011_1111,
            0b1111_1111,
            0b1101_0011,
            // 133     |11111111|11111111|010100
            0b1111_1111,
            0b1111_1111,
            (0b0001_0100 << 2)
                // 134     |11111111|11111111|010101
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1101,
            (0b0000_0101 << 4)
                // 135     |11111111|11111111|1011001
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1011,
            (0b0000_0001 << 5)
                // 136     |11111111|11111111|010110
                + 0b0001_1111,
            0b1111_1111,
            0b1110_1011,
            (0b0000_0000 << 7)
                // 137     |11111111|11111111|1011010
                + 0b0111_1111,
            0b1111_1111,
            0b1101_1010,
            // 138     |11111111|11111111|1011011
            0b1111_1111,
            0b1111_1111,
            (0b0101_1011 << 1)
                // 139     |11111111|11111111|1011100
                + 0b0000_0001,
            0b1111_1111,
            0b1111_1111,
            (0b0001_1100 << 2)
                // 140     |11111111|11111111|1011101
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1110,
            (0b0001_1101 << 3)
                // 141     |11111111|11111111|1011110
                + 0b0000_0111,
            0b1111_1111,
            0b1111_1101,
            (0b0000_1110 << 4)
                // 142     |11111111|11111111|11101011
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_1011 << 4)
                // 143     |11111111|11111111|1011111
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1011,
            (0b0000_0111 << 5)
                // 144     |11111111|11111111|11101100
                + 0b0001_1111,
            0b1111_1111,
            0b1111_1101,
            (0b0000_0100 << 5)
                // 145     |11111111|11111111|11101101
                + 0b0001_1111,
            0b1111_1111,
            0b1111_1101,
            (0b0000_0101 << 5)
                // 146     |11111111|11111111|010111
                + 0b0001_1111,
            0b1111_1111,
            0b1110_1011,
            (0b0000_0001 << 7)
                // 147     |11111111|11111111|1100000
                + 0b0111_1111,
            0b1111_1111,
            0b1110_0000,
            // 148     |11111111|11111111|11101110
            0b1111_1111,
            0b1111_1111,
            0b1110_1110,
            // 149     |11111111|11111111|1100001
            0b1111_1111,
            0b1111_1111,
            (0b0110_0001 << 1)
                // 150     |11111111|11111111|1100010
                + 0b0000_0001,
            0b1111_1111,
            0b1111_1111,
            (0b0010_0010 << 2)
                // 151     |11111111|11111111|1100011
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1111,
            (0b0000_0011 << 3)
                // 152     |11111111|11111111|1100100
                + 0b0000_0111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_0100 << 4)
                // 153     |11111111|11111110|11100
                + 0b0000_1111,
            0b1111_1111,
            0b1110_1110,
            (0b0000_0000 << 7)
                // 154     |11111111|11111111|011000
                + 0b0111_1111,
            0b1111_1111,
            (0b0101_1000 << 1)
                // 155     |11111111|11111111|1100101
                + 0b0000_0001,
            0b1111_1111,
            0b1111_1111,
            (0b0010_0101 << 2)
                // 156     |11111111|11111111|011001
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1101,
            (0b0000_1001 << 4)
                // 157     |11111111|11111111|1100110
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1100,
            (0b0000_0110 << 5)
                // 158     |11111111|11111111|1100111
                + 0b0001_1111,
            0b1111_1111,
            0b1111_1001,
            (0b0000_0011 << 6)
                // 159     |11111111|11111111|11101111
                + 0b0011_1111,
            0b1111_1111,
            0b1111_1011,
            (0b0000_0011 << 6)
                // 160     |11111111|11111111|011010
                + 0b0011_1111,
            0b1111_1111,
            0b1101_1010,
            // 161     |11111111|11111110|11101
            0b1111_1111,
            0b1111_1110,
            (0b0001_1101 << 3)
                // 162     |11111111|11111110|1001
                + 0b0000_0111,
            0b1111_1111,
            0b1111_0100,
            (0b0000_0001 << 7)
                // 163     |11111111|11111111|011011
                + 0b0111_1111,
            0b1111_1111,
            (0b0101_1011 << 1)
                // 164     |11111111|11111111|011100
                + 0b0000_0001,
            0b1111_1111,
            0b1111_1110,
            (0b0001_1100 << 3)
                // 165     |11111111|11111111|1101000
                + 0b0000_0111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_1000 << 4)
                // 166     |11111111|11111111|1101001
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1101,
            (0b0000_0001 << 5)
                // 167     |11111111|11111110|11110
                + 0b0001_1111,
            0b1111_1111,
            0b1101_1110,
            // 168     |11111111|11111111|1101010
            0b1111_1111,
            0b1111_1111,
            (0b0110_1010 << 1)
                // 169     |11111111|11111111|011101
                + 0b0000_0001,
            0b1111_1111,
            0b1111_1110,
            (0b0001_1101 << 3)
                // 170     |11111111|11111111|011110
                + 0b0000_0111,
            0b1111_1111,
            0b1111_1011,
            (0b0000_0110 << 5)
                // 171     |11111111|11111111|11110000
                + 0b0001_1111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_0000 << 5)
                // 172     |11111111|11111110|11111
                + 0b0001_1111,
            0b1111_1111,
            0b1101_1111,
            // 173     |11111111|11111111|011111
            0b1111_1111,
            0b1111_1111,
            (0b0001_1111 << 2)
                // 174     |11111111|11111111|1101011
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1111,
            (0b0000_1011 << 3)
                // 175     |11111111|11111111|1101100
                + 0b0000_0111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_1100 << 4)
                // 176     |11111111|11111111|00000
                + 0b0000_1111,
            0b1111_1111,
            0b1111_0000,
            (0b0000_0000 << 7)
                // 177     |11111111|11111111|00001
                + 0b0111_1111,
            0b1111_1111,
            (0b0010_0001 << 2)
                // 178     |11111111|11111111|100000
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1110,
            (0b0000_0000 << 4)
                // 179     |11111111|11111111|00010
                + 0b0000_1111,
            0b1111_1111,
            0b1111_0001,
            (0b0000_0000 << 7)
                // 180     |11111111|11111111|1101101
                + 0b0111_1111,
            0b1111_1111,
            0b1110_1101,
            // 181     |11111111|11111111|100001
            0b1111_1111,
            0b1111_1111,
            (0b0010_0001 << 2)
                // 182     |11111111|11111111|1101110
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1111,
            (0b0000_1110 << 3)
                // 183     |11111111|11111111|1101111
                + 0b0000_0111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_1111 << 4)
                // 184     |11111111|11111110|1010
                + 0b0000_1111,
            0b1111_1111,
            0b1110_1010,
            // 185     |11111111|11111111|100010
            0b1111_1111,
            0b1111_1111,
            (0b0010_0010 << 2)
                // 186     |11111111|11111111|100011
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1110,
            (0b0000_0011 << 4)
                // 187     |11111111|11111111|100100
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1001,
            (0b0000_0000 << 6)
                // 188     |11111111|11111111|1110000
                + 0b0011_1111,
            0b1111_1111,
            0b1111_1000,
            (0b0000_0000 << 7)
                // 189     |11111111|11111111|100101
                + 0b0111_1111,
            0b1111_1111,
            (0b0110_0101 << 1)
                // 190     |11111111|11111111|100110
                + 0b0000_0001,
            0b1111_1111,
            0b1111_1111,
            (0b0000_0110 << 3)
                // 191     |11111111|11111111|1110001
                + 0b0000_0111,
            0b1111_1111,
            0b1111_1111,
            (0b0000_0001 << 4)
                // 192     |11111111|11111111|11111000|00
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0010_0000 << 2)
                // 193     |11111111|11111111|11111000|01
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1111,
            0b1110_0001,
            // 194     |11111111|11111110|1011
            0b1111_1111,
            0b1111_1110,
            (0b0000_1011 << 4)
                // 195     |11111111|11111110|001
                + 0b0000_1111,
            0b1111_1111,
            (0b0111_0001 << 1)
                // 196     |11111111|11111111|100111
                + 0b0000_0001,
            0b1111_1111,
            0b1111_1111,
            (0b0000_0111 << 3)
                // 197     |11111111|11111111|1110010
                + 0b0000_0111,
            0b1111_1111,
            0b1111_1111,
            (0b0000_0010 << 4)
                // 198     |11111111|11111111|101000
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1010,
            (0b0000_0000 << 6)
                // 199     |11111111|11111111|11110110|0
                + 0b0011_1111,
            0b1111_1111,
            0b1111_1101,
            (0b0000_0100 << 5)
                // 200     |11111111|11111111|11111000|10
                + 0b0001_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0000_0010 << 3)
                // 201     |11111111|11111111|11111000|11
                + 0b0000_0111,
            0b1111_1111,
            0b1111_1111,
            (0b0110_0011 << 1)
                // 202     |11111111|11111111|11111001|00
                + 0b0000_0001,
            0b1111_1111,
            0b1111_1111,
            0b1111_0010,
            (0b0000_0000 << 7)
                // 203     |11111111|11111111|11111011|110
                + 0b0111_1111,
            0b1111_1111,
            0b1111_1101,
            (0b0000_1110 << 4)
                // 204     |11111111|11111111|11111011|111
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0101_1111 << 1)
                // 205     |11111111|11111111|11111001|01
                + 0b0000_0001,
            0b1111_1111,
            0b1111_1111,
            0b1111_0010,
            (0b0000_0001 << 7)
                // 206     |11111111|11111111|11110001
                + 0b0111_1111,
            0b1111_1111,
            0b1111_1000,
            (0b0000_0001 << 7)
                // 207     |11111111|11111111|11110110|1
                + 0b0111_1111,
            0b1111_1111,
            0b1111_1011,
            (0b0000_0001 << 6)
                // 208     |11111111|11111110|010
                + 0b0011_1111,
            0b1111_1111,
            (0b0001_0010 << 3)
                // 209     |11111111|11111111|00011
                + 0b0000_0111,
            0b1111_1111,
            0b1111_1000,
            (0b0000_0011 << 6)
                // 210     |11111111|11111111|11111001|10
                + 0b0011_1111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_0110 << 4)
                // 211     |11111111|11111111|11111100|000
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0110_0000 << 1)
                // 212     |11111111|11111111|11111100|001
                + 0b0000_0001,
            0b1111_1111,
            0b1111_1111,
            0b1111_1000,
            (0b0000_0001 << 6)
                // 213     |11111111|11111111|11111001|11
                + 0b0011_1111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_0111 << 4)
                // 214     |11111111|11111111|11111100|010
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0110_0010 << 1)
                // 215     |11111111|11111111|11110010
                + 0b0000_0001,
            0b1111_1111,
            0b1111_1111,
            (0b0111_0010 << 1)
                // 216     |11111111|11111111|00100
                + 0b0000_0001,
            0b1111_1111,
            0b1111_1110,
            (0b0000_0100 << 4)
                // 217     |11111111|11111111|00101
                + 0b0000_1111,
            0b1111_1111,
            0b1111_0010,
            (0b0000_0001 << 7)
                // 218     |11111111|11111111|11111010|00
                + 0b0111_1111,
            0b1111_1111,
            0b1111_1101,
            (0b0000_0000 << 5)
                // 219     |11111111|11111111|11111010|01
                + 0b0001_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0000_1001 << 3)
                // 220     |11111111|11111111|11111111|1101
                + 0b0000_0111,
            0b1111_1111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_0001 << 7)
                // 221     |11111111|11111111|11111100|011
                + 0b0111_1111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_0011 << 4)
                // 222     |11111111|11111111|11111100|100
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0110_0100 << 1)
                // 223     |11111111|11111111|11111100|101
                + 0b0000_0001,
            0b1111_1111,
            0b1111_1111,
            0b1111_1001,
            (0b0000_0001 << 6)
                // 224     |11111111|11111110|1100
                + 0b0011_1111,
            0b1111_1111,
            (0b0010_1100 << 2)
                // 225     |11111111|11111111|11110011
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1111,
            (0b0011_0011 << 2)
                // 226     |11111111|11111110|1101
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1011,
            (0b0000_0001 << 6)
                // 227     |11111111|11111111|00110
                + 0b0011_1111,
            0b1111_1111,
            (0b0110_0110 << 1)
                // 228     |11111111|11111111|101001
                + 0b0000_0001,
            0b1111_1111,
            0b1111_1111,
            (0b0000_1001 << 3)
                // 229     |11111111|11111111|00111
                + 0b0000_0111,
            0b1111_1111,
            0b1111_1001,
            (0b0000_0011 << 6)
                // 230     |11111111|11111111|01000
                + 0b0011_1111,
            0b1111_1111,
            (0b0110_1000 << 1)
                // 231     |11111111|11111111|1110011
                + 0b0000_0001,
            0b1111_1111,
            0b1111_1111,
            (0b0011_0011 << 2)
                // 232     |11111111|11111111|101010
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1110,
            (0b0000_1010 << 4)
                // 233     |11111111|11111111|101011
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1010,
            (0b0000_0011 << 6)
                // 234     |11111111|11111111|11110111|0
                + 0b0011_1111,
            0b1111_1111,
            0b1111_1101,
            (0b0000_0110 << 5)
                // 235     |11111111|11111111|11110111|1
                + 0b0001_1111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_1111 << 4)
                // 236     |11111111|11111111|11110100
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0000_0100 << 4)
                // 237     |11111111|11111111|11110101
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0000_0101 << 4)
                // 238     |11111111|11111111|11111010|10
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0010_1010 << 2)
                // 239     |11111111|11111111|1110100
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1111,
            (0b0001_0100 << 3)
                // 240     |11111111|11111111|11111010|11
                + 0b0000_0111,
            0b1111_1111,
            0b1111_1111,
            (0b0110_1011 << 1)
                // 241     |11111111|11111111|11111100|110
                + 0b0000_0001,
            0b1111_1111,
            0b1111_1111,
            0b1111_1001,
            (0b0000_0010 << 6)
                // 242     |11111111|11111111|11111011|00
                + 0b0011_1111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_1100 << 4)
                // 243     |11111111|11111111|11111011|01
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0010_1101 << 2)
                // 244     |11111111|11111111|11111100|111
                + 0b0000_0011,
            0b1111_1111,
            0b1111_1111,
            0b1111_0011,
            (0b0000_0001 << 7)
                // 245     |11111111|11111111|11111101|000
                + 0b0111_1111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_1000 << 4)
                // 246     |11111111|11111111|11111101|001
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0110_1001 << 1)
                // 247     |11111111|11111111|11111101|010
                + 0b0000_0001,
            0b1111_1111,
            0b1111_1111,
            0b1111_1010,
            (0b0000_0010 << 6)
                // 248     |11111111|11111111|11111101|011
                + 0b0011_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0000_1011 << 3)
                // 249     |11111111|11111111|11111111|1110
                + 0b0000_0111,
            0b1111_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0000_0000 << 7)
                // 250     |11111111|11111111|11111101|100
                + 0b0111_1111,
            0b1111_1111,
            0b1111_1110,
            (0b0000_1100 << 4)
                // 251     |11111111|11111111|11111101|101
                + 0b0000_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0110_1101 << 1)
                // 252     |11111111|11111111|11111101|110
                + 0b0000_0001,
            0b1111_1111,
            0b1111_1111,
            0b1111_1011,
            (0b0000_0010 << 6)
                // 253     |11111111|11111111|11111101|111
                + 0b0011_1111,
            0b1111_1111,
            0b1111_1111,
            (0b0000_1111 << 3)
                // 254     |11111111|11111111|11111110|000
                + 0b0000_0111,
            0b1111_1111,
            0b1111_1111,
            0b1111_0000,
            // 255     |11111111|11111111|11111011|10
            0b1111_1111,
            0b1111_1111,
            0b1111_1011,
            (0b0000_0010 << 6)
                // end filler
                + 0b0011_1111,
        ];
        let values: Vec<u8> = (0..=255).collect();
        let res = values.hpack_encode();
        assert_eq!(res, Ok(bytes));
    }

    use super::super::HpackStringDecode;

    #[test]
    fn byte_count_exact_when_bit_count_multiple_of_8() {
        let encoded = vec![
            0x8c, 0x2d, 0x4b, 0x70, 0xdd, 0xf4, 0x5a, 0xbe, 0xfb, 0x40, 0x05, 0xdb,
        ];

        let mut res = Vec::new();
        for byte in encoded.hpack_decode() {
            res.push(byte.unwrap());
        }

        let reencoded = res.hpack_encode();

        assert_eq!(reencoded.unwrap().last(), Some(&0xdb));
    }

    #[test]
    fn byte_() {
        let encoded = vec![
            0x55, 0x92, 0xbe, 0xff, 0x48, 0x36, 0xcb, 0x86, 0x37, 0x3d, 0x68, 0xca, 0xc9, 0x61,
            0xce, 0xde, 0xdc, 0xe5, 0xfc,
        ];

        let mut res = Vec::new();
        for byte in encoded.hpack_decode() {
            res.push(byte.unwrap());
        }

        let reencoded = res.hpack_encode();

        assert_eq!(reencoded.unwrap().last(), Some(&0xfc));
    }
}
